/**
 * @author       <Me>
 * @version      1.0
 * @date         2024-10-05
 * @description  事件管理器 这段代码定义了一个事件管理器 EventManager，
 * 用于处理事件的注册、注销和触发，适用于需要事件驱动编程的场景
 */
// 这行代码导入了一个单例基类 Singleton，该类控制 EventManager 类只有一个实例，以确保全局使用时的一致性。
import Singleton from 'db://assets/Base/Singleton'

// 这里定义了一个接口 IItem，用于表示一个事件处理项，包含两个属性：
// func: 处理事件的函数。
// ctx: 函数执行时的上下文（可以是任何类型）。
interface IItem {
  func: Function
  ctx: unknown
}

// 通过继承 Singleton 类，定义了事件管理器类 EventManager。
// 这是一个单例类，确保在应用中只有一个事件管理实例。
export default class EventManager extends Singleton {
  // 这是一个静态方法，用于获取 EventManager 的唯一实例。
  static get Instance() {
    return super.GetInstance<EventManager>()
  }
  //eventDic 用于存储事件名称及其对应的处理函数列表。
  // 这里使用了 Map 数据结构，其中键是事件名称，值是处理该事件的函数数组。
  private eventDic: Map<string, Array<IItem>> = new Map()

  // on 方法用于注册事件。当调用此方法时，先检查 eventDic 是否已有该事件名称:
  // 若存在，则将该事件的函数和上下文对象添加到数组中。
  // 若不存在，则创建一个新的数组并将其添加到 eventDic 中。
  on(eventName: string, func: Function, ctx: unknown) {
    if (this.eventDic.has(eventName)) {
      this.eventDic.get(eventName).push({ func, ctx })
    } else {
      this.eventDic.set(eventName, [{ func, ctx }])
    }
  }
  // off 方法用于注销已注册的事件。
  // 它通过事件名称查找对应的函数，
  // 如果找到则通过 findIndex 方法查找该函数在数组中的索引并移除。
  off(eventName: string, func: Function) {
    if (this.eventDic.has(eventName)) {
      const index = this.eventDic.get(eventName).findIndex(i => i.func === func)
      index > -1 && this.eventDic.get(eventName).splice(index, 1)
    }
  }
  // emit 方法用于触发指定事件。它查找 eventDic 中对应的事件数组，
  // 并对每个处理项调用其函数，传入参数。
  // 如果提供了上下文（ctx），则用 apply 方法绑定上下文；否则，直接调用。
  emit(eventName: string, ...params: unknown[]) {
    if (this.eventDic.has(eventName)) {
      this.eventDic.get(eventName).forEach(({ func, ctx }) => {
        ctx ? func.apply(ctx, params) : func(...params)
      })
    }
  }
  // clear 方法用于清空所有注册的事件，重置 eventDic 为一个空的 Map。
  clear() {
    this.eventDic.clear()
  }
}
